from pkgutil import get_data
from flask import Flask, render_template, request, redirect, url_for
import pandas as pd
import re
import requests
from bs4 import BeautifulSoup
import matplotlib.pyplot as plt
import json

import pymysql
from flask import Flask, request, render_template
from datetime import datetime
import requests
from py.login import check_user
from py.users import create_user_table, get_all_users, create_user_table_html, insert_user, delete_user
import os

base_dir = os.path.dirname(os.path.abspath(__file__))
app = Flask(
    __name__,
    template_folder=os.path.join(base_dir, 'templates'),
    static_folder=os.path.join(base_dir, 'static'),
)

url = 'http://lishi.tianqi.com/mianyang/201905.html'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
    'Cookie': 'lianjia_uuid=9d3277d3-58e4-440e-bade-5069cb5203a4; UM_distinctid=16ba37f7160390-05f17711c11c3e-454c0b2b-100200-16ba37f716618b; _smt_uid=5d176c66.5119839a; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2216ba37f7a942a6-0671dfdde0398a-454c0b2b-1049088-16ba37f7a95409%22%2C%22%24device_id%22%3A%2216ba37f7a942a6-0671dfdde0398a-454c0b2b-1049088-16ba37f7a95409%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_referrer_host%22%3A%22%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%7D%7D; _ga=GA1.2.1772719071.1561816174; Hm_lvt_9152f8221cb6243a53c83b956842be8a=1561822858; _jzqa=1.2532744094467475000.1561816167.1561822858.1561870561.3; CNZZDATA1253477573=987273979-1561811144-%7C1561865554; CNZZDATA1254525948=879163647-1561815364-%7C1561869382; CNZZDATA1255633284=1986996647-1561812900-%7C1561866923; CNZZDATA1255604082=891570058-1561813905-%7C1561866148; _qzja=1.1577983579.1561816168942.1561822857520.1561870561449.1561870561449.1561870847908.0.0.0.7.3; select_city=110000; lianjia_ssid=4e1fa281-1ebf-e1c1-ac56-32b3ec83f7ca; srcid=eyJ0Ijoie1wiZGF0YVwiOlwiMzQ2MDU5ZTQ0OWY4N2RiOTE4NjQ5YmQ0ZGRlMDAyZmFhODZmNjI1ZDQyNWU0OGQ3MjE3Yzk5NzFiYTY4ODM4ZThiZDNhZjliNGU4ODM4M2M3ODZhNDNiNjM1NzMzNjQ4ODY3MWVhMWFmNzFjMDVmMDY4NWMyMTM3MjIxYjBmYzhkYWE1MzIyNzFlOGMyOWFiYmQwZjBjYjcyNmIwOWEwYTNlMTY2MDI1NjkyOTBkNjQ1ZDkwNGM5ZDhkYTIyODU0ZmQzZjhjODhlNGQ1NGRkZTA0ZTBlZDFiNmIxOTE2YmU1NTIxNzhhMGQ3Yzk0ZjQ4NDBlZWI0YjlhYzFiYmJlZjJlNDQ5MDdlNzcxMzAwMmM1ODBlZDJkNmIwZmY0NDAwYmQxNjNjZDlhNmJkNDk3NGMzOTQxNTdkYjZlMjJkYjAxYjIzNjdmYzhiNzMxZDA1MGJlNjBmNzQxMTZjNDIzNFwiLFwia2V5X2lkXCI6XCIxXCIsXCJzaWduXCI6XCIzMGJlNDJiN1wifSIsInIiOiJodHRwczovL2JqLmxpYW5qaWEuY29tL3p1ZmFuZy9yY28zMS8iLCJvcyI6IndlYiIsInYiOiIwLjEifQ=='
}

#获取数据格式化
def format_analysis(content: str) -> list:
    # 去除首尾空白
    content = content.strip()

    # 自动分段逻辑（支持多种分隔符）
    separators = r'(\n\n+|\\n\\n|；|。|\. )'
    paragraphs = re.split(separators, content)

    # 过滤空段落并合并分隔符
    processed = []
    buffer = ''
    for p in paragraphs:
        if re.match(separators, p):
            if buffer:
                processed.append(buffer.strip())
                buffer = ''
        else:
            buffer += p
    if buffer:
        processed.append(buffer.strip())

    return processed if len(processed) > 1 else [content]

app = Flask(__name__)

#首页
@app.route('/')
def hello_world():  # put application's code here
    return render_template('login.html')

#登录页
@app.route('/login', methods=["POST"])
def login():  # put application's code here
    print(request.form)
    username = request.form.get('username')
    password = request.form.get('password')

    key = check_user(username, password)
    if key:
        return render_template('index.html')
    else:
        return render_template('login_error.html')

#获取空气质量页
API_KEY = "520693f5c4614bedb7cba7b710c4c517"
def get_location_id(city_name):
    """获取城市Location ID"""
    url = "https://geoapi.qweather.com/v2/city/lookup"
    params = {
        "location": city_name,
        "key": API_KEY,
        "range": "cn",
        "number": 1
    }
    try:
        response = requests.get(url, params=params)
        data = response.json()
        if data["code"] == "200" and data.get("location"):
            return data["location"][0]["id"]
        return None
    except:
        return None
def get_weather_data(location_id):
    """获取天气和空气质量数据"""
    weather_url = "https://devapi.qweather.com/v7/weather/now"
    air_url = "https://devapi.qweather.com/v7/air/now"

    params = {"location": location_id, "key": API_KEY}

    try:
        weather_res = requests.get(weather_url, params=params)
        weather_data = weather_res.json()
        air_res = requests.get(air_url, params=params)
        air_data = air_res.json()

        if weather_data["code"] == "200" and air_data["code"] == "200":
            return {
                "weather": weather_data["now"],
                "air": air_data["now"]
            }
        return None
    except:
        return None
def format_time(iso_str):
    """格式化时间"""
    try:
        dt = datetime.fromisoformat(iso_str.replace("+08:00", ""))
        return dt.strftime("%Y-%m-%d %H:%M")
    except:
        return iso_str
@app.route('/welcome', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        city = request.form.get('city', '').strip()
        if not city:
            return render_template('error.html', message="请输入城市名称")

        location_id = get_location_id(city)
        if not location_id:
            return render_template('error.html', message="城市信息获取失败")

        data = get_weather_data(location_id)
        if not data:
            return render_template('error.html', message="天气数据获取失败")

        result = {
            'city': city,
            'weather': {
                '观测时间': format_time(data['weather']['obsTime']),
                '温度 (℃)': data['weather']['temp'],
                '体感温度 (℃)': data['weather']['feelsLike'],
                '天气状况': data['weather']['text'],
                '风向': data['weather']['windDir'],
                '风力等级': data['weather']['windScale'],
                '风速 (km/h)': data['weather']['windSpeed'],
                '湿度 (%)': data['weather']['humidity'],
                '降水量 (mm)': data['weather']['precip'],
                '气压 (hPa)': data['weather']['pressure'],
                '能见度 (km)': data['weather']['vis'],
                '云量 (%)': data['weather']['cloud'],
                '露点温度 (℃)': data['weather']['dew']
            },
            'air': {
                'AQI指数': data['air']['aqi'],
                '空气质量': data['air']['category'],
                '首要污染物': data['air']['primary'] if data['air']['primary'] != 'NA' else '无'
            }
        }

        result_ds = str(result)

        API_KEY_ds = "sk-dd5295eb97fb42a09cb836a25ed59e3b"
        url_ds = "https://api.deepseek.com/chat/completions"
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {API_KEY_ds}"
        }
        data = {
            "model": "deepseek-chat",
            # R1-deepseek-reasoner
            "messages": [
                {"role": "system", "content": "你是一名空气质量和天气情况预警员"},
                {"role": "user",
                 "content": "下面的数据是城市空气质量和天气情况" + result_ds + "帮我根据所给的内容写20字左右的预警信息，只写预警信息就好了，其余的什么都不用写"}
            ],
            "stream": False
        }
        response = requests.post(url_ds, headers=headers, json=data)
        if response.status_code == 200:
            result_1 = response.json()
            print(result_1['choices'][0]['message']['content'])
            ds_data = result_1['choices'][0]['message']['content'].strip()
        else:
            print("请求失败，错误码：", response.status_code)

        return render_template('result.html', result=result,data=ds_data)

    return render_template('index_1.html')


def get_weather(city):
    api_key = 'b201f1d7c3c9236965949ea259ec488d'
    url = f'https://restapi.amap.com/v3/weather/weatherInfo?key={api_key}&city={city}&extensions=base'
    response = requests.get(url)
    data = response.json()
    return data

#污染物模拟实验
@app.route('/yangshi_3')
def yangshi_3():  # put application's code here
    return render_template('yangshi_3.html')

#北京地区空气质量可视化分析
API_KEY = "520693f5c4614bedb7cba7b710c4c517"
CACHE = {}
def fetch_geo_data(city):
    """独立地理数据获取"""
    url = "https://geoapi.qweather.com/v2/city/lookup"
    try:
        resp = requests.get(url, params={
            "location": city,
            "key": API_KEY,
            "range": "cn",
            "number": 1
        }, timeout=10)
        data = resp.json()
        if data.get("code") == "200" and data.get("location"):
            return {
                "id": data["location"][0]["id"],
                "name": data["location"][0]["name"],
                "lat": data["location"][0]["lat"],
                "lon": data["location"][0]["lon"]
            }
        return None
    except Exception as e:
        print(f"地理数据获取失败: {str(e)}")
        return None
def fetch_weather_data(location_id):
    """独立气象数据获取"""
    weather_url = "https://devapi.qweather.com/v7/weather/now"
    air_url = "https://devapi.qweather.com/v7/air/now"

    try:
        # 获取天气数据
        weather_resp = requests.get(weather_url, params={
            "location": location_id,
            "key": API_KEY
        }, timeout=10)
        weather = weather_resp.json().get("now", {})

        # 获取空气质量数据
        air_resp = requests.get(air_url, params={
            "location": location_id,
            "key": API_KEY
        }, timeout=10)
        air = air_resp.json().get("now", {})

        return {
            "weather": weather,
            "air": air
        }
    except Exception as e:
        print(f"气象数据获取失败: {str(e)}")
        return None
@app.route('/yangshi_2')
def yangshi_2():  # put application's code here
    city = request.args.get('city', '北京')

    if city in CACHE:
        return render_template('analysis.html', data=CACHE[city])

    geo = fetch_geo_data(city)
    if not geo:
        return render_template('error.html', message="城市数据获取失败")
    weather_data = fetch_weather_data(geo["id"])
    if not weather_data:
        return render_template('error.html', message="气象数据获取失败")
    analysis_data = {
        "city": geo["name"],
        "coordinates": f"{geo['lat']}, {geo['lon']}",
        "indicators": {
            "temp": float(weather_data["weather"].get("temp", 0)),
            "feelsLike": float(weather_data["weather"].get("feelsLike", 0)),
            "humidity": float(weather_data["weather"].get("humidity", 0)),
            "windSpeed": float(weather_data["weather"].get("windSpeed", 0)),
            "aqi": int(weather_data["air"].get("aqi", 0)),
            "pressure": float(weather_data["weather"].get("pressure", 0)),
            "cloud": float(weather_data["weather"].get("cloud", 0)),
            "precip": float(weather_data["weather"].get("precip", 0))
        },
        "status": {
            "weather": weather_data["weather"].get("text", ""),
            "airQuality": weather_data["air"].get("category", ""),
            "primaryPollutant": weather_data["air"].get("primary", "无")
        }
    }
    # 缓存数据
    CACHE[city] = analysis_data
    print(analysis_data)
    return render_template('analysis.html', data=analysis_data)

#全国各地空气质量可视化分析
@app.route('/yangshi_1', methods=['GET', 'POST'])
def weather_analysis():
    if request.method == 'POST':
        city = request.form.get('city', '').strip()
        # 缓存检查
        if city in CACHE:
            return render_template('analysis.html', data=CACHE[city])

        # 获取地理数据
        geo = fetch_geo_data(city)
        if not geo:
            return render_template('error.html', message="城市数据获取失败")

        # 获取气象数据
        weather_data = fetch_weather_data(geo["id"])
        if not weather_data:
            return render_template('error.html', message="气象数据获取失败")

        # 数据标准化处理
        analysis_data = {
            "city": geo["name"],
            "coordinates": f"{geo['lat']}, {geo['lon']}",
            "indicators": {
                "temp": float(weather_data["weather"].get("temp", 0)),
                "feelsLike": float(weather_data["weather"].get("feelsLike", 0)),
                "humidity": float(weather_data["weather"].get("humidity", 0)),
                "windSpeed": float(weather_data["weather"].get("windSpeed", 0)),
                "aqi": int(weather_data["air"].get("aqi", 0)),
                "pressure": float(weather_data["weather"].get("pressure", 0)),
                "cloud": float(weather_data["weather"].get("cloud", 0)),
                "precip": float(weather_data["weather"].get("precip", 0))
            },
            "status": {
                "weather": weather_data["weather"].get("text", ""),
                "airQuality": weather_data["air"].get("category", ""),
                "primaryPollutant": weather_data["air"].get("primary", "无")
            }
        }
        # 缓存数据
        CACHE[city] = analysis_data
        return render_template('analysis.html', data=analysis_data)

    return render_template("index_2.html")




#空气质量预测
@app.route('/yangshi_4', methods=['GET', 'POST'])
def wea_an():
    if request.method == 'POST':
        city = request.form.get('city', '').strip()

        # 获取地理数据
        geo = fetch_geo_data(city)
        if not geo:
            return render_template('error.html', message="城市数据获取失败")

        # 获取气象数据
        weather_data = fetch_weather_data(geo["id"])
        if not weather_data:
            return render_template('error.html', message="气象数据获取失败")

        # 数据标准化处理
        analysis_data = {
            "city": geo["name"],
            "coordinates": f"{geo['lat']}, {geo['lon']}",
            "indicators": {
                "temp": float(weather_data["weather"].get("temp", 0)),
                "feelsLike": float(weather_data["weather"].get("feelsLike", 0)),
                "humidity": float(weather_data["weather"].get("humidity", 0)),
                "windSpeed": float(weather_data["weather"].get("windSpeed", 0)),
                "aqi": int(weather_data["air"].get("aqi", 0)),
                "pressure": float(weather_data["weather"].get("pressure", 0)),
                "cloud": float(weather_data["weather"].get("cloud", 0)),
                "precip": float(weather_data["weather"].get("precip", 0))
            },
            "status": {
                "weather": weather_data["weather"].get("text", ""),
                "airQuality": weather_data["air"].get("category", ""),
                "primaryPollutant": weather_data["air"].get("primary", "无")
            }
        }
        # 缓存数据
        CACHE[city] = analysis_data

        ds_str = str(analysis_data)
        #空气质量预测
        API_KEY_ds = "sk-dd5295eb97fb42a09cb836a25ed59e3b"
        url_ds = "https://api.deepseek.com/chat/completions"
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {API_KEY_ds}"
        }
        data = {
            "model": "deepseek-chat",
            # R1-deepseek-reasoner
            "messages": [
                {"role": "system", "content": "你是一名空气质量和天气情况预测员"},
                {"role": "user", "content": "下面的数据是城市空气质量和天气情况"+ds_str+"帮我根据所给的信息预测一下未来4天的空气质量与天气情况,不用回复类似“根据提供的数据”的话，直接写内容就好了，一共分4天，每一天单独一段话"}
            ],
            "stream": False
        }
        response = requests.post(url_ds, headers=headers, json=data)
        if response.status_code == 200:
            result = response.json()
            print(result['choices'][0]['message']['content'])
            ds_jg = result['choices'][0]['message']['content'].strip()
        else:
            print("请求失败，错误码：", response.status_code)

        return render_template('txt.html', data = format_analysis(ds_jg))

    return render_template('index_3.html')




@app.route('/ksh')
def ksh():  # put application's code here
    get_data()
    datas = pd.DataFrame(
        {'日期': date_box, '星期': week_box, '最高温度': max_temp, '最低温度': min_temp, '天气': weh, '风向': wind})
    datas.to_csv('D:\天气数据.csv', encoding='utf_8_sig')
    print(datas)

    # keshihuatu
    # 设置Seaborn样式

    # 最高温度和最低温度随时间变化的折线图
    plt.figure(figsize=(12, 6))
    plt.plot(datas['日期'], datas['最高温度'], label='最高温度', marker='o')
    plt.plot(datas['日期'], datas['最低温度'], label='最低温度', marker='o')
    plt.xlabel('日期')
    plt.ylabel('温度 (℃)')
    plt.title('最高温度和最低温度随时间变化')
    plt.xticks(rotation=45)
    plt.legend()
    plt.tight_layout()
    plt.show()

    # 最高温度 vs. 最低温度的散点图
    plt.figure(figsize=(8, 6))

    plt.xlabel('最高温度 (℃)')
    plt.ylabel('最低温度 (℃)')
    plt.title('最高温度 vs. 最低温度')
    plt.tight_layout()
    plt.show()

    return render_template('ksh.html')


def set_link(year):
    # year参数为需要爬取数据的年份
    link = []
    for i in range(1, 3):
        if i < 10:
            url = 'http://lishi.tianqi.com/mianyang/{}0{}.html'.format(year, i)
        else:
            url = 'http://lishi.tianqi.com/mianyang/{}{}.html'.format(year, i)
        link.append(url)
    return link


def get_page(url, headers):
    html = requests.get(url, headers=headers)
    if html.status_code == 200:
        html.encoding = html.apparent_encoding
        return html.text
    else:
        return None


date_box = []
max_temp = []
min_temp = []
weh = []
wind = []
week_box = []

DB_HOST = 'localhost'
DB_USER = 'root'
DB_PASSWORD = '010615'
DB_NAME = 'qxyt2'

conn = pymysql.connect(host=DB_HOST, user=DB_USER, password=DB_PASSWORD, database=DB_NAME, charset='utf8mb4',
                       cursorclass=pymysql.cursors.DictCursor)


@app.route('/eva')
def eva():  # put application's code here
    # 从数据库中获取所有评论
    with conn.cursor() as cursor:
        cursor.execute('SELECT * FROM comments')
        comments = cursor.fetchall()
    return render_template('eva.html', comments=comments)
    return render_template('eva.html')


@app.route('/add_comment', methods=['POST'])
def add_comment():
    name = request.form['name']
    text = request.form['text']

    # 将新评论插入到数据库
    with conn.cursor() as cursor:
        cursor.execute('INSERT INTO comments (name, text) VALUES (%s, %s)', (name, text))
        conn.commit()

    # 重新加载页面以显示新评论
    return eva()


# 主页
@app.route('/users')
def user():
    create_user_table()
    users = get_all_users()
    user_table = create_user_table_html(users)
    return render_template('user.html', user_table=user_table)


# 添加用户页面
@app.route('/add', methods=['GET', 'POST'])
def add_user():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        insert_user(username, password)
        return redirect(url_for('user'))
    return render_template('add_user.html')


# xxmm
@app.route('/xxmm', methods=['GET', 'POST'])
def xxmm():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        insert_user(username, password)
        return redirect(url_for('user'))
    return render_template('change-password.html')


# 删除用户
@app.route('/delete/<int:user_id>')
def delete(user_id):
    delete_user(user_id)
    return redirect(url_for('user'))


@app.route('/explain')
def explain():  # put application's code here
    # 从数据库中获取所有评论

    return render_template('explain.html')

#获取爬虫数据

# 数据库配置
DB_CONFIG = {
    'host': 'localhost',
    'user': 'root',
    'password': '010615',
    'db': 'qxyt2',
    'charset': 'utf8mb4',
    'cursorclass': pymysql.cursors.DictCursor
}


def get_aqi_data():
    connection = pymysql.connect(**DB_CONFIG)
    try:
        with connection.cursor() as cursor:
            sql = "SELECT * FROM aqi_data"
            cursor.execute(sql)
            result = cursor.fetchall()

            processed_data = []
            quality_dist = {'优': 0, '良': 0, '轻度污染': 0, '中度污染': 0, '重度污染': 0, '严重污染': 0, '极度污染': 0}
            parse_fail_count = 0

            for item in result:
                try:
                    aqi_num = int(item['aqi_value'].split()[0])
                    quality = item['aqi_value'].split()[1]
                    processed_data.append({
                        'city': item['city_name'],
                        'aqi': aqi_num,
                        'quality': quality,
                        'time': item['update_time']
                    })
                    if quality in quality_dist:
                        quality_dist[quality] += 1
                except:
                    parse_fail_count += 1

            return processed_data, quality_dist, parse_fail_count
    finally:
        connection.close()
@app.route('/pc', methods=['GET', 'POST'])
def dashboard():
    data, quality_dist, parse_fail = get_aqi_data()

    # 处理图表数据
    sorted_data = sorted(data, key=lambda x: x['aqi'], reverse=True)
    top10_cities = sorted_data[:10]  # 确保变量名称与模板一致

    # 调试输出
    print("Top10 Cities:", [item['city'] for item in top10_cities])
    print("Quality Distribution:", quality_dist)

    return render_template('text2.html',
                           top10_cities=top10_cities,
                           quality_dist=quality_dist,
                           parse_fail=parse_fail)


if __name__ == '__main__':
    app.run(debug=False)
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文显示
    plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
    app.run()
